package cn.edu.scau.cmi.ema.service;

import cn.edu.scau.cmi.ema.base.CmiPagination;
import cn.edu.scau.cmi.ema.domain.Eventqualitytype;
import cn.edu.scau.cmi.ema.domain.Qualitytype;
import cn.edu.scau.cmi.ema.service.base.CmiEmaService;
import cn.edu.scau.cmi.ema.util.CmiSqlUtil;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import java.util.*;
@Service("QualitytypeService")
@Transactional

public class QualitytypeServiceImpl extends CmiEmaService implements QualitytypeService {
	public QualitytypeServiceImpl() {
	}

	@Transactional
	public Qualitytype saveQualitytype(Qualitytype qualitytype) {
		Set<Eventqualitytype> existingEventqualitytypesForQualitytype = new HashSet<Eventqualitytype>();

		Set<Eventqualitytype> selectedEventqualitytypesForQualitytype = qualitytype
				.getEventqualitytypesForQualitytype();

		if (qualitytype.getId() == null) {

			Qualitytype existingQualitytype = qualitytypeDAO.findQualitytypeByPhysicalPrimaryKey(qualitytype.getName());

			if (isEquals(qualitytype, existingQualitytype)) {
				return existingQualitytype;
			}

			qualitytype = qualitytypeDAO.store(qualitytype);
			qualitytypeDAO.flush();

			for (Eventqualitytype relatedEventqualitytype : selectedEventqualitytypesForQualitytype) {
				relatedEventqualitytype.setQualitytype(qualitytype);
				eventqualitytypeDAO.store(relatedEventqualitytype);
			}
		} else {
			Qualitytype existingQualitytype = qualitytypeDAO.findQualitytypeByPrimaryKey(qualitytype.getId());

			existingEventqualitytypesForQualitytype = existingQualitytype.getEventqualitytypesForQualitytype();

			Set<Eventqualitytype> prepareDeleteEventqualitytypesForQualitytype = new HashSet<Eventqualitytype>();
			Set<Eventqualitytype> prepareAddEventqualitytypesForQualitytype = new HashSet<Eventqualitytype>();

			prepareDeleteEventqualitytypesForQualitytype.addAll(selectedEventqualitytypesForQualitytype);
			prepareDeleteEventqualitytypesForQualitytype.addAll(existingEventqualitytypesForQualitytype);

			prepareAddEventqualitytypesForQualitytype.addAll(selectedEventqualitytypesForQualitytype);
			prepareAddEventqualitytypesForQualitytype.addAll(existingEventqualitytypesForQualitytype);

			prepareDeleteEventqualitytypesForQualitytype.removeAll(selectedEventqualitytypesForQualitytype);
			prepareAddEventqualitytypesForQualitytype.removeAll(existingEventqualitytypesForQualitytype);

			for (Eventqualitytype relatedEventqualitytype : prepareAddEventqualitytypesForQualitytype) {
				relatedEventqualitytype.setQualitytype(qualitytype);
				eventqualitytypeDAO.store(relatedEventqualitytype);
			}

			for (Eventqualitytype relatedEventqualitytype : prepareDeleteEventqualitytypesForQualitytype) {
				relatedEventqualitytype.setQualitytype(null);
				eventqualitytypeDAO.store(relatedEventqualitytype);
			}
			qualitytype = qualitytypeDAO.store(qualitytype);
			qualitytypeDAO.flush();
		}

		eventqualitytypeDAO.flush();
		return qualitytype;
	}

	public void deleteQualitytype(Qualitytype qualitytype) {
		qualitytypeDAO.remove(qualitytype);
		qualitytypeDAO.flush();
	}

	@Transactional
	public void deleteQualitytypes(Set<Integer> deleteQualitytypesId) {
		Query query = qualitytypeDAO.createNamedQuery("deleteQualitytypesById", -1, -1);
		query.setParameter(1, deleteQualitytypesId);
		query.executeUpdate();
	}

	@Transactional
	public Set<Qualitytype> loadQualitytypes() {
		return qualitytypeDAO.findAllQualitytypes();

	}

	@Transactional
	public Set<Qualitytype> loadReferenceQualitytypes(Set<Qualitytype> qualitytypes) {
		Iterator<Qualitytype> qualitytypesIterator = qualitytypes.iterator();
		Set<Qualitytype> referencedQualitytypes = new HashSet<>();
		while (qualitytypesIterator.hasNext()) {
			Qualitytype currentQualitytype = qualitytypesIterator.next();

			if (!currentQualitytype.getEventqualitytypesForQualitytype().isEmpty()) {
				referencedQualitytypes.add(currentQualitytype);
				continue;
			}
		}
		return referencedQualitytypes;
	}

	public Set<Qualitytype> loadQualitytypesByIdSet(Set<Integer> qualitytypeIdSet) {

		Iterator<Integer> qualitytypeIdIterator = qualitytypeIdSet.iterator();
		Set<Qualitytype> qualitytypeSet = new HashSet<>();
		while (qualitytypeIdIterator.hasNext()) {
			Integer id = qualitytypeIdIterator.next();
			Qualitytype currentQualitytype = qualitytypeDAO.findQualitytypeById(id);
			qualitytypeSet.add(currentQualitytype);
		}
		return qualitytypeSet;
	}

	@Transactional
	public List<Qualitytype> findAllQualitytypes(Integer startResult, Integer maxRows) {
		return new java.util.ArrayList<Qualitytype>(qualitytypeDAO.findAllQualitytypes(startResult, maxRows));
	}

	@Transactional
	public Qualitytype findQualitytypeByPrimaryKey(Integer id) {
		return qualitytypeDAO.findQualitytypeByPrimaryKey(id);
	}

	@Transactional
	public Integer countQualitytypes() {
		return ((Long) qualitytypeDAO.createQuerySingleResult("select count(o) from Qualitytype o").getSingleResult())
				.intValue();
	}

	@Transactional
	public Integer countQualitytypes(CmiPagination page) {
		String sql = CmiSqlUtil.createCountHql(page, Qualitytype.class);
		return ((Long) qualitytypeDAO.createQuerySingleResult(sql).getSingleResult()).intValue();
	}

	/**
	 * search for name with ajax
	 *
	 */
	@Transactional
	public Integer countQualitytypesByName(String queryName) {
		Query query = qualitytypeDAO.createNamedQuery("countQualitytypesByName", -1, -1);
		query.setParameter(1, queryName);
		return new Long((long) query.getSingleResult()).intValue();
	}

	@Transactional
	public Integer countQualitytypesByDetachedCriteria(CmiPagination page) {
		DetachedCriteria detachedCriteria = CmiSqlUtil.createDetachedCriteria(page, Qualitytype.class);
		Session session = (Session) entityManager.getDelegate();
		detachedCriteria.setProjection(Projections.rowCount());
		return new Long((long) detachedCriteria.getExecutableCriteria(session).uniqueResult()).intValue();
	}

	public Map<String, ?> loadQualitytypeObjectReferencedSet(Qualitytype qualitytype) {
		HashMap<String, Object> objectReferencedSetMap = new HashMap<>();

		Set<Integer> eventqualitytypesIds = new HashSet<Integer>();
		for (Eventqualitytype obj : qualitytype.getEventqualitytypesForQualitytype()) {

			eventqualitytypesIds.add(obj.getId());
		}
		objectReferencedSetMap.put("eventqualitytypesIds", eventqualitytypesIds);

		return objectReferencedSetMap;
	}

	public Map<String, ?> loadQualitytypeClassReferencedSet(Qualitytype qualitytype) {
		HashMap<String, Object> classReferencedSetMap = new HashMap<>();
		classReferencedSetMap.put("eventqualitytypes", eventqualitytypeDAO.findAllEventqualitytypes());

		return classReferencedSetMap;
	}

	public boolean isEquals(Qualitytype qualitytype, Object obj) {
		if (obj == qualitytype)
			return true;
		if (!(obj instanceof Qualitytype))
			return false;
		Qualitytype comparedQualitytype = (Qualitytype) obj;
		if (!CheckPropertyEqual(qualitytype.getName(), comparedQualitytype.getName())) {
			return false;
		}
		return true;
	}

	public static <T> boolean CheckPropertyEqual(T originProperty, T comparedProperty) {
		// 基本类型经过参数传递后会自动装箱
		String[] className = originProperty.getClass().getName().split("\\.");
		if (className[0].equals("java") && className[1].equals("math")) {
			return ((Comparable) originProperty).compareTo(comparedProperty) == 0 ? true : false;
		} else {
			return originProperty.equals(comparedProperty);
		}
	}
}

